/*
 * TsMediaMuxer.cpp
 *
 *  Created on: 2020年4月29日
 *      Author: chuanjiang.zh
 */

#include "TsMediaMuxer.h"
#include "FfmpegTsMuxer.h"


class TsMediaMuxerPrivate
{
public:

	TsMediaMuxerPrivate()
	{
	}

	void firePacket(UMediaPacket& pkt)
	{
		if (m_sink)
		{
			m_sink(pkt);
		}
	}

	void setSink(UMediaMuxer::Sink sink)
	{
		m_sink = sink;
	}


	UMediaMuxer::Sink	m_sink;

	av::FfmpegTsMuxer	m_muxer;

};



TsMediaMuxer::TsMediaMuxer() :
	m_pimp(new TsMediaMuxerPrivate())
{
}

TsMediaMuxer::~TsMediaMuxer()
{
	close();

	delete m_pimp;
	m_pimp = nullptr;
}

bool TsMediaMuxer::open(const UMediaFormat& fmt)
{
	m_pimp->m_muxer.open(fmt);
	m_format = fmt;

	auto sink = std::bind(&TsMediaMuxer::handlePacket, this, std::placeholders::_1,
		std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
	m_pimp->m_muxer.setSink(sink);

	return m_format.isValid();
}

void TsMediaMuxer::close()
{
	m_pimp->m_muxer.close();
}

bool TsMediaMuxer::isOpen()
{
	return m_format.isValid();
}


bool TsMediaMuxer::getOutFormat(UMediaFormat& fmt)
{
	fmt = m_format;
	return m_format.isValid();
}

bool TsMediaMuxer::input(UMediaPacket& pkt)
{
	if (pkt.size() <= 0)
	{
		return false;
	}

	if (!m_pimp)
	{
		return false;
	}

	return m_pimp->m_muxer.write(pkt.type(), pkt.data(), pkt.size(), pkt.pts(), pkt.duration(), pkt.flags());
}

void TsMediaMuxer::setSink(Sink sink)
{
	m_pimp->setSink(sink);
}

void TsMediaMuxer::handlePacket(uint8_t* data, int size, int64_t pts, int flags)
{
	UMediaPacket packet;
	packet.newPacket(size);
	packet.set_type(UMEDIA_TYPE_DATA);
	packet.set_pts(pts);
	packet.set_dts(pts);
	packet.set_flags(flags);
	
	packet.copy(data, size);

	m_pimp->firePacket(packet);
}

const char* TsMediaMuxer::getName()
{
    return "ts";
}